{Titrator 3.01 is a chemical equilibrium calculator intended for use in aqueous }
{  systems with acid/base, complexation, dissociation, precipitation and }
{  electron transfer reactions. }

{Titrator was designed primarily as a teaching tool for chemistry, }
{  biochemistry, geochemistry and environmental chemistry.  It is purely an }
{  equilibrium calculator, and lacks the database, transport, and kinetic  }
{  capabilities of more complex and sophisticated programs.  The user must }
{  provide the stoichiometry and log K value (or enthalpy and entropy) }
{  of each chemical species to be considered.}

{The algorithm is based upon the MicroQL logic of J. Westall, which in turn }
{   follows the algorithm in the MINEQL program of Westall and FMM Morel.}

{Currently documentation is incomplete, but may be useful and includes    }
{       TiManual        Users manual in .doc and .pdf                     }
{       TiTutorial      Tutorial based on a calcite system, .doc and .pdf }


{Current version 3.01, released under GPL by Steve Cabaniss, Dept. of Chemistry }
{  University of New Mexico, who can be contacted at cabaniss@unm.edu}

{*****************************************************************************}

{TitrDefs contains the constant values, type declarations and
 data structure definitions for the Titrator program.
 It also contains the declarations of the global variables used throughout
 the program.}

unit TitrDefs;

 {$R+}     {Range checking turned on}

interface

Const   MaxComps     = 40;              { Maximum # Components in a system}
        MaxSpecs     = 200;             { Maximum # Species in a system}
        NumConc      = MaxComps + MaxSpecs; { max # [species] monitored}
        NDataPts     = 201;             { Max # points in a titration }
                                        { which is also length of data arrays}
        MaxMCReps    = 10000;           { maximum # MC points }
        ErrorMax = 10;                  { Maximum # of MC Errors tolerated }
        GasR         = 8.314;           { gas constant in J/mol K}
        LogConvr     = 2.3025851;       { Constant to convert ln to log }
        MaxBins      = 100;             { Max bins in MC results distribution }
        NumHelp      = 18;              { Number of help files available}
Type

        {Begin by declaring the basic types for chemical equilibrium systems:
        {    Species- each chemical entity present in the system, defined by
        {       stoichiometry and formation constant
        {    Component - the chemical 'building blocks' of all species
        {    System Definition- the chemical data set compromised of the
        {       components, species and ancillary information for a single
        {       aqueous solution. }

        Str20 = string[20];             {used for labels}

        {CompType designates the information known about a component- is the
        {total amount or fixed activity known, is it a gas or a surface, etc.}

        CompType = (CTotDiss, CFixDiss, CRedox, CGas, CSolid, CSurface);

        {CTotDiss:  The total amount of dissolved component is known}
        {CFixDiss:  The activity of the dissolved species is known}
        {CRedox:    The component is the redox potential}
        {CGas:      The partial pressure of the gas is fixed and known}
        {CSolid:    The solid is present with activity = 1}
        {CSurface:  Represents an adsorbing surface}

        CompTypeNum = array[CTotDiss .. CSurface] of integer;
        CompTypeLabel = array[CTotDiss .. CSurface] of string;

        SpecType = (Diss, Solid, Gas, Surface, Sorbed);
        {Diss:     Dissolved species}
        {Solid:    Ionic or molecular solid}
        {Gas:      Gas phase}
        {Surface:  Solid surface
        {Sorbed:   Adsorbed species on surface}

        SpecTypeNum = array[Diss..Sorbed] of integer;
        SpecTypeLabel = array[Diss..Sorbed] of string;

        Display = (Molar, mM, uM, ppm, atm);

     {Components are the fundamental building blocks of the system - }
     {all chemical species are simple combinations of components}

        Component = record
               Name      :       str20;         { Component Label }
               CType     :       CompType;      { Component Type }
               Charge    :       integer;       { ionic charge or 0 neutral }
               IonSize   :       double;        { ionic radius for IS calcs}
               Weight    :       double;        { weight in amu}
               TotalX    :       double;        { Mass balance constraint }
               GuessX    :       double;        { Log Initial Guess at final Free }
               FreeX     :       double;        { Log Molarity at Equilibrium }
               Conc      :       double;        { Molarity at equilibrium}
               DisplayX  :       double;        { value to display}
               DispUnits :       display;       { preferred units in display}
               Error     :       double;        { Mass balance error (T-Tcalc)}
               StdDev    :       double         { standard deviation in the }
                                                { calc. total or free [comp] }
             end;

     {A chemical species is any stoichiometrically distinct chemical}
     {entity- for example, acetic acid and acetate are two different species}

         Specie = record
               Name      :       str20;         { Species Label }
               SType     :       SpecType;      { Type }
               Coeff     :       array[1..MaxComps] of integer;
                                                { exponents in formation K }
               LogK      :       double;        { log K of formation }
               KCalc     :       Boolean;       { True-calculate K from H and S}
               DeltaH    :       double;        { enthalpy of formation, kJ/mol}
               DeltaS    :       double;        { Entropy of formation}
               DeltaG    :       double;        { Gibbs free energy kJ/mol}
               IonSize   :       double;        { ionic radius for IS calcs}
               Conc      :       double;        { Equilibrium Concentration, M}
               LogC      :       double;        { Log of equilibrium molarity}
               DispUnits :       display;       { units to display concentration}
               DisplayC  :       double;        { value to display}
               StdDev    :       double;        { Standard deviation in log K}
               Charge    :       integer;       { Species charge }
             end;

         {For example, the species carbonic acid, bicarbonate and carbonate
         { can all be represented a combinations of the components H+ and CO3--
         { H2CO3  is formed from 1 CO3-- and 2 H+
         { HCO3-  is formed from 1 CO3-- and 1 H+
         { CO3--  is formed from 1 CO3-- and 0 H+     }

         Header = record                        { descriptive info on set }
                Title    :       string[20];    { title of data set }
                Descrip  :       array[1..3] of string[80]
              end;

      CompList = array[1..MaxComps] of Component;     { Component storage }
      SpecList = array[1..MaxSpecs] of Specie;        { Species storage }

      Dataset = record                       {holds the information }
                                             {defining an equilibrium system}
              Head    : Header;              { Title and description }
              comps   : CompList;            { Components }
              specs   : SpecList;            { Species }
              NComp   : integer;             { Total number of components }
              NSpec   : integer;             { Total number of species }
              CTypeNum : CompTypeNum;  {numbers of various component types}
              STypeNum : SpecTypeNum;  {Numbers of various species types}

              Temperature : Double;    {Temperature in Kelvin}
              ThermoCalc : Boolean;    {True indicates log must be calculated}
                                       {from temperature and DeltaH, DeltaS }
              Mu : Double;             {ionic strength from D-H theory}
              UseMu : Boolean;         {Make ionic strength corrections}
              FindMu : Boolean;        {True mean calculate IS iteratively}
                                       {False means use fixed Mu value}

          end;                       {end of the system definition section}



{****************************************************************************}

      {The types declared below are used for titration data handling}

      TitrType = (TiNone, TiTotal, TiFree, TiLogK, TiTemp, TiMu);
      Vector = array[1..MaxComps] of double;         { holds data during }
      Matrix = array[1..MaxComps] of Vector;         { actual calculations }
      IntVector = array[1..MaxComps] of integer;     { holds charge data }
      SpecArray = array[1..MaxSpecs] of double;      { species properties }
      SpecInts = array[1..MaxSpecs] of integer;      { species properties }
      Coef = array[1..MaxComps] of SpecArray;        { stoichiometric }
      Title = string[20];                            { a file title }

      {DataArray is used to hold results of titrations for plotting, etc.}
      DataArray = array[1..NDataPts] of double;
      DataMatrix = array[1..NumConc] of DataArray;  { spreadsheet for
                                                       titration results }

  {**************************************************************************}
     {Types for Monte Carlo and Sensitivity calculations }

      StatType = (TrueValue, Mean, StdDev, Skewness, Kurtosis);   {Descriptive statistics}
      StatNames = array[TrueValue..Kurtosis] of string;
      Stats = array[TrueValue..Kurtosis] of double;    {Set of 4 DS for a given conc}
      ConcStats = array[1..NumConc] of Stats;     {Array of DS for all conc}
      SweepStats = array[1..NDataPts] of ConcStats; {array of DS for a titration}
      MCConc = array[1..MaxMCReps] of double;  {All conc values for one species}
                                               {in a MC simulation}

      {Concs variables hold concentrations of all species and components}
      Concs = array[1..NumConc] of double;

      {SensiMat is a sensitivity matrix containing the derivative}
      {of each concentration with respect to each constraint}
      SensiMat = array[1..NumConc] of Concs;

      {An MCResult holds the calculated concentrations of all species for all}
      {Monte Reps for a problem}
      MCResult = array[1..MaxMCReps] of Concs;

      {MCFreqs holds frequencies of various results in an MC simulation}
      MCFreqs = array[1..MaxBins] of integer;

      {MCbounds holds the ranges of the frequancies}
      MCBounds = array[1..MaxBins] of double;

      {MonteResult is used only in error propagation simulations}
      {MonteResult = array[1..MonteMax] of double;    { results from MC calc.}


 {****************************************************************************}

      {The display counters are used to control the screen displays}
      CompDisp = (CompName, CType, CTotal, CFree, CLogX,
                  CLogGuess, CStdDev, Cerror, CCharge);
      CDispStrings = array[CompName..CCharge] of string[14];

      UnitLabels = array[0..6] of string[14];

      SpecDisp = (SpecName, SType, SpecMolarity, SLogC, SLogK, StD, SDelH, SDelS,
                 SDelG, SCharge, SStoichiometry);
      SDispStrings = array[SpecName..SStoichiometry] of string[14];

      EditMode = (Add, Edit, Delete, None);

      {HelpStrings contains the names of help topics and files}
      HelpStrings = array[1..NumHelp] of string[20];

Const
      BlanComp : Component = (Name: ''; Ctype: CTotDiss; Charge: 0; Weight: 0;
            TotalX: 0; GuessX: 0; FreeX: 0; Conc: 0; Error: 0; StdDev: 0);
      BlanSpec : Specie = (Name:''; SType:Diss; Coeff:(0,0,0,0,0,0,0,0,0,
                 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
                           LogK:0; Conc :0; LogC : 0; StdDev:0);
      {TiLabels : array[0..4] of str20 = ('No Titration', 'Type I Component',
                 'Type II Component', 'Species Log K', 'Ionic Strength');   }

      CompTitles : CDispStrings = ('Component', 'Type', 'Total Molarity',
                'Free Molarity', 'Log Free M', 'Log Free Guess',
               'Std. Dev.', 'Balance Error', 'Charge');

      SpecTitles : SDispStrings = ('Species', 'Type', 'Molarity', 'Log M',
              'Log K', 'Std Dev', 'Delta H kJ/mol', 'Delta S J/molK',
              'Delta G kJ/mol', 'Charge', 'Stoichiometry');

      CompTypeTitles : CompTypeLabel = ('Total     ', 'Free      ', 'Redox E   ',
                'Gas       ', 'Solid     ', 'Surface   ');

      SpecTypeTitles : SpecTypeLabel = ('Dissolved ','Solid     ','Gas       ',
                'Surface   ', 'Sorbed    ');

      XUnit : UnitLabels = ('M', 'milliM', 'microM', 'nanoM', 'picoM', 'femtoM',
           'attoM');

      StatStrings : StatNames = ('True_Value', 'Mean', 'Std_Dev', 'Skewness', 'Kurtosis');

      HelpTopics : HelpStrings =
        ('General', 'Terminology', 'Define a system', 'Components',
         'Species', 'Solve a System', 'Titrate', 'Sweep', 'Temperature',
         'Ionic Strength', 'Description', 'Iterative Controls', 'Filing',
         'Graphing', 'Gases', 'Solids', 'Monte Carlo', 'Sensitivity');

      HelpFiles : HelpStrings = ('General', 'Terminology', 'Define', 'Component',
         'Species', 'Solve', 'Titrate', 'Sweep', 'Temperature',
         'IS', 'Description', 'Iterative', 'Filing', 'Graphing', 'Gases',
         'Solids', 'MonteCarlo', 'Sensitivity');


Var
    EditC     : integer;        {# of component to edit }
    EditS     : integer;        {# of species to edit}

    EdComp    : component;      {newly edited component}
    EdSpec    : specie;         {newly edited species}
    EdMode    : EditMode;       {is user adding new, deleting, editing or }
                                {not changing the selecting component/species?}

    {These Boolean flags report on whether the minimization has converged}
    {and if not, what type of non-convergence was observed}

    Done      :   Boolean;      { Set true when calculation finished}
    MassOK    :   Boolean;      { Set true when mass error is <tolerance}
    TooMany   :   Boolean;      { Set true if # iterations exceeds ItMax}
    PhaseViol :   Boolean;      { Set true if phase rule is violated}
    MatError  :   Boolean;      { Set true if matrix inversion fails }

    {This is a convenient way to refer to an entire system definition-  }
    {but currently only one dataset is allowed in the current version   }

    S         :   Dataset;      { Components and species for Calculations}
    OriginalSystem : DataSet;   { Keeps original values during a titration}

    {These variable control the convergence criteria}
    ItMax     :   Integer;      { Maximum number of iterations alloweed}
    Toler     :   double;       { the maximum fractional error mass balance }
                                { tolerated in a 'solved' system}

    Tot       :   vector;       { Total amount of component present in moles/L}
    TotErr    :   vector;       { Calculated error in Tot }
    FreeX     :   vector;       { Component Concentration in Free form (molar)}
    LogX      :   vector;       { Log base 10 of FreeX concentrations}

    Conc         :   SpecArray;    { Species concentrations, molar units }
    LogK         :   SpecArray;    { Log of Species formation constants}
    A            :   Coef;         { stoichiometric coefficients }
    NewX         :   vector;       { new estimate of FreeX from matrix solution}

    LogKZero     :   Specarray;    { species K at Mu=0 }
    SpecChg      :   SpecInts;     { species charge }
    Charge       :   IntVector;    { component charge }
    Kadjust      :   SpecArray;    { ionic strength adjustment }
    Iter         :   integer;      { counts the number of iterations }


    {The following section contains variables used in the Sweep module}
    {which allows continuous variation of one component}

    XData   : DataArray;           { independent (swept) variable }
    XPlot   : DataArray;           { XData scaled to mM, uM, etc. }
    YPlot   : DataArray;           { Y data scaled to mM, etc.}

    MaxOrd  : integer;             { order of magnitude to multiply }
                                   { Xdata to get XPlot}
    MaxYVal : double;              { Maximum value of Y to Plot }
    YOrd    : integer;             { order of magnitude to multiply }
                                   { YData to get YPlot}

    YData   : DataMatrix;          { dependent (monitored) variables }
    TitrX   : Integer;             { # of swept component }
    GoTitrate : Boolean;
    SweepDone : Boolean;       {has sweep been completed?}

    {Labels  : array[1..21] of string[12];     { names of comps & specs }
    TitrPts : integer;                        { points in sweep }
    Delta   : double;                         { increment in sweep }
    NumY    : integer;                        { # dependent data arrays }
    TitrHead: header;                         { description of results }
    TiType  : TitrType;                       { Type of X variable }
    InitialPt: double;                        { First X value in sweep}
    FinalPt : double;                         { Last X value in sweep }

    TrueX   : double;                         { original value of X }

    {The variables in the following section are used for specifying and }
    {controlling the simulated titrations }

    V0       : double;           { Volume of solution to be titrated, in L}
    DeltaVol : double;           { Volume of titrant added for each point, in L}
    VolAdded : DataArray;        { array of volume (X) data in simulation}
    Vfinal   : double;           { final titrant volume in titration}

    TitrCation : Integer;             { # of first titrated component (cation)}
    TitrAnion : integer;              { # of second titrated component (anion)}
    CationConc : double;              { molar conc. of cation }
    AnionConc : double;               { molar con. of anion}

    GoSimulate : Boolean;
    SimulationDone : Boolean;          {has Simulation been completed?}

    SimuPts : integer;                        { points in simulated titration }
    SimuHead: header;                         { description of results }

    LogMolar : integer;               {graph scale code: 0 = Molarity       }
                                      {                  1 = log(molarity)  }


    {The following variables are used in the Help System}

    HelpIndex : integer;               {Help file to display}
    HelpDir : string;                  {Location of help files}

    {***********************************************************************}

    {The variables below are employed in the Monte Carlo uncertainty }
    {simulations}

    EnableMonte : Boolean;       { TRUE- MC calcs available}
                                 { FALSE- MC unavailable; used to 'turn off'}
                                 { MC for simpler distribution}
    Monte : Boolean;             { True- perform MC; False- do not perform}
    MCReps  : Integer;           { # of MC reps per point }
    RSeed : integer;             { seed for random number generator}
    ErrCode : integer;           { Error code for Monte Carlo calcs}
    MCPoint : MCResult;          { Results for all realizations of a MC point}
    Frequencies : MCFreqs;       { Counts or frequencies in a MC distribution}
    FreqBins : MCBounds;         { boundaries for bins of the above}
    MCPointSum : ConcStats;      { Summary Stats for a single MC point}
    MCSweepSum : SweepStats;     { Summary Stats for an MC Sweep}

    MCDone  : Boolean;                        { TRUE = MC calculation completed}
    SensDone : Boolean;                       { Sensitivity matrix calculated}
    GraphC  : integer;                        { Species to plot }
    MCSave  : Boolean;                        { Save log[] results to disk ? }
    MCStatSave : Boolean;                     { Save MC summary Stats to disk}
    MonteFile : Text;                         { Text file for MC log[] data }
    MonteFileBase : Str20;                    { Root Name of above File }
    MonteStatFileBase : Str20;                { Root Name of Stats File }
    MonteName : Str20;                        { Root Name + counter}
    CountString : String[2];
    OneCon : Boolean;                      { True - MC w/ only one constraint}
    ChosenCon : integer;                   { the one constraint selected }

    SensSave : Boolean;                  { Save Sensitivity Matrix? }
    SensFile : Str20;                    { File name for Sensitivity matrix}
    DiffX : double;                      { Difference in X for derivative calcs}
                                         { for sensitivities }
    Sensitivities : SensiMat;            { Sensitivity matrix }

    DeltaX : Vector;                          { predicted error in X }
    DeltaC : SpecArray;                       { predicted error in C }
    DMult : double;                           { error prediction interval }

    Hibin, LoBin : double;                    { Bounds for distribution }
    BinWidth : double;                        { delta for one bin }
    Distrib : MCFreqs;                        { distribution in Surface }
    NumBins : integer;                        { number of bins in current
                                                    distribution }


implementation

end.
